import React from 'react';
import { Transition } from 'react-transition-group';
import { IModalProps, TContext, ICompoundComponents } from './Modal.types';
import { Portal } from '..';
import { StyledModal, Backdrop } from './Modal.styled';
import { useOnClickOutside } from '../hooks/useOnClickOutside';
import Title from './Title';
import Content from './Content';
import Actions from './Actions';
import './Modal.scss';

/**
 * @function ModalContext - Контекст модального окна.
 */
export const ModalContext = React.createContext<TContext>({
    inhereModal: false
});

/**
* @function Modal - Отображает модальное окно с составными компонентами.
* @param { IModalProps } props - Объект props, содержащий свойства модального окна.
* @return { React.ReactElement } - Составные компоненты модального окна.
*/
const Modal: React.FC<IModalProps & React.RefAttributes<HTMLElement>> & ICompoundComponents = React.forwardRef<HTMLElement, IModalProps>((
    {
        children,
        container,
        closeOnOutsideClick,
        displayCloseIcon,
        onClose,
        showModal,
        ...nextProps
    },
    ref

): React.ReactElement => {

    const internalRef = React.useRef<HTMLDivElement>(null);

    React.useImperativeHandle(ref, () => internalRef.current);

    useOnClickOutside({
        onClickOutside: onClose,
        ref: internalRef,
        enabled: closeOnOutsideClick
    });

    React.useEffect(() => {
        /**
         * @function handleKeyDown - Обработчик события нажатия на кнопку Escape.
         * @param { KeyboardEvent } event - событие нажатия на кнопку.
         */
        const handleKeyDown = (event: KeyboardEvent) => {
            if (event.key === "Escape") {
                onClose();
            }
        }

        document.body.addEventListener('keydown', handleKeyDown);

        return () => {
            document.body.removeEventListener('keydown', handleKeyDown);
            document.body.classList.remove('scroll-lock');
        }

    }, []);

    /**
     * Добавляет класс к body для блокировки прокрутки.
     */
    React.useEffect(() => {
        if (showModal) {
            document.body.classList.add('scroll-lock');
        } else {
            document.body.classList.remove('scroll-lock');
        }
    }, [showModal]);


    /**
     * @function contextValue - Мемоизирует параметры контекста.
     */
    const contextValue = React.useMemo(() => ({
        onClose,
        displayCloseIcon,
        inhereModal: true
    }), [onClose, displayCloseIcon]);

    return (
        <ModalContext.Provider value={contextValue}>
            <Transition
                in={showModal}
                timeout={200}
                unmountOnExit
                nodeRef={internalRef}
            >
                {
                    (state) =>
                    (
                        <Portal portalElement={container}>
                            <Backdrop className={`transit-${state}`} />
                            <StyledModal
                                ref={internalRef}
                                className={`transition-${state}`}
                                tabIndex={0}
                                {...nextProps}
                            >
                                {children}
                            </StyledModal>
                        </Portal>
                    )
                }
            </Transition>
        </ModalContext.Provider>
    );
});

Modal.Title = Title;
Modal.Content = Content;
Modal.Actions = Actions;

Modal.defaultProps = {
    displayCloseIcon: true,
    closeOnOutsideClick: true
};

Modal.displayName = 'Modal';

export default Modal;
